package org.proteored.miapeapi.xml.pride.adapter;

import java.util.List;

import org.apache.log4j.Logger;
import org.proteored.miapeapi.cv.ControlVocabularyManager;
import org.proteored.miapeapi.cv.SampleProcessingStep;
import org.proteored.miapeapi.cv.msi.DataTransformation;
import org.proteored.miapeapi.experiment.model.Experiment;
import org.proteored.miapeapi.experiment.model.Replicate;
import org.proteored.miapeapi.experiment.model.filters.FDRFilter;
import org.proteored.miapeapi.experiment.model.filters.Filter;
import org.proteored.miapeapi.interfaces.Adapter;
import org.proteored.miapeapi.interfaces.ms.MSAdditionalInformation;
import org.proteored.miapeapi.interfaces.ms.MiapeMSDocument;
import org.proteored.miapeapi.xml.pride.autogenerated.CvParamType;
import org.proteored.miapeapi.xml.pride.autogenerated.ExperimentType.Protocol;
import org.proteored.miapeapi.xml.pride.autogenerated.ExperimentType.Protocol.ProtocolSteps;
import org.proteored.miapeapi.xml.pride.autogenerated.ObjectFactory;
import org.proteored.miapeapi.xml.pride.autogenerated.ParamType;
import org.proteored.miapeapi.xml.pride.util.PrideControlVocabularyXmlFactory;

/**
 * The protocol element defines the sample processing steps that have been
 * performed.
 * 
 * @author Salva
 * 
 */
public class ProtocolAdapterFromExperiment implements Adapter<Protocol> {
	private static Logger log = Logger.getLogger("log4j.logger.org.proteored");

	private final ObjectFactory factory;

	private final PrideControlVocabularyXmlFactory prideCvUtil;

	private final Experiment experiment;

	private final MiapeMSDocument mergedMIAPEMS;

	private final ControlVocabularyManager cvManager;

	public ProtocolAdapterFromExperiment(ObjectFactory factory,
			ControlVocabularyManager cvManager, Experiment experiment) {
		this.factory = factory;
		this.experiment = experiment;
		this.prideCvUtil = new PrideControlVocabularyXmlFactory(factory,
				cvManager);
		this.cvManager = cvManager;
		// unify MIAPE MSs
		final List<MiapeMSDocument> miapeMSs = this.experiment.getMiapeMSs();
		this.mergedMIAPEMS = MzDataAdapter.unifyMiapeMSs(miapeMSs, cvManager);
	}

	@Override
	public Protocol adapt() {
		Protocol protocol = factory.createExperimentTypeProtocol();
		ProtocolSteps protocolSteps = factory
				.createExperimentTypeProtocolProtocolSteps();

		// SampleProcessingSteps from additional informations
		if (this.mergedMIAPEMS != null) {
			List<MSAdditionalInformation> addInfos = this.mergedMIAPEMS
					.getAdditionalInformations();
			for (MSAdditionalInformation msAdditionalInformation : addInfos) {
				String value = msAdditionalInformation.getValue();
				String name = msAdditionalInformation.getName();

				log.info("getting cvParam from sample processing step in sample information");
				CvParamType cvParam = prideCvUtil.createCvParam(name, value,
						SampleProcessingStep.getInstance(cvManager));
				if (cvParam != null) {
					ParamType cvParamList = factory.createParamType();
					cvParamList.getCvParamOrUserParam().add(cvParam);
					protocolSteps.getStepDescription().add(cvParamList);
					log.info("Added '" + cvParam.getName() + "'='"
							+ cvParam.getValue() + "' '"
							+ cvParam.getAccession() + "' as a protocol step");
				}
			}

		}

		if (this.experiment != null) {
			if (this.experiment.getReplicates() != null
					&& this.experiment.getReplicates().size() > 1) {
				String replicateNames = "";
				for (Replicate replicate : experiment.getReplicates()) {
					if (!"".equals(replicateNames))
						replicateNames += ", ";
					replicateNames += replicate.getName();
				}
				// Data processing integration
				ParamType paramList = factory.createParamType();
				prideCvUtil
						.addCvParamOrUserParamToParamType(
								paramList,
								"data processing",
								"This dataset is resulting from the data integration of "
										+ experiment.getReplicates().size()
										+ " different datasets, using the ProteoRed MIAPE Extractor and the PAnalyzer algorithm",
								DataTransformation.getInstance(cvManager));
				protocolSteps.getStepDescription().add(paramList);

			} else if (this.experiment.getReplicates().size() == 1) {
				ParamType userParamList = factory.createParamType();
				prideCvUtil.addUserParamToParamType(userParamList,
						"Experiment composed by one identification set",
						this.experiment.getReplicates().get(0).getName());
				protocolSteps.getStepDescription().add(userParamList);
			}

			// Data filtering
			final List<Filter> filters = this.experiment.getFilters();
			final FDRFilter fdrFilter = this.experiment.getFDRFilter();
			if (fdrFilter != null)
				filters.add(fdrFilter);
			if (filters != null && !filters.isEmpty()) {
				StringBuilder sb = new StringBuilder();
				for (Filter filter : filters) {
					if (!"".equals(sb.toString()))
						sb.append(", ");
					sb.append(filter.toString());
				}
				ParamType paramList = factory.createParamType();
				prideCvUtil.addCvParamOrUserParamToParamType(paramList,
						"data filtering",
						"The following filters were applied: " + sb.toString(),
						DataTransformation.getInstance(cvManager));
				protocolSteps.getStepDescription().add(paramList);
			}
		}
		if (protocolSteps.getStepDescription().size() > 0) {
			protocol.setProtocolSteps(protocolSteps);
			protocol.setProtocolName("PRIDE XML created using the ProteoRed MIAPE Extractor");
		} else {
			protocol.setProtocolName("no protocols captured");
		}
		return protocol;
	}
}
